/**
 * command.js
 *
 * @file 命令模式与宏命令模式基类
 * */

/**
 * Command - 命令类
 *
 * @class
 * @extends Object
 * */
export const Command = function (command) {
    return {
        command: command,
        /**
         * execute - 执行宏命令
         *
         * @function
         * @memberOf Command
         * */
        execute: function () {
            this.command();
        }
    }
}

/**
 * MacroCommand - 宏命令
 *
 * @class
 * @extends Object
 * */
export const MacroCommand = function (...commands) {
    return {
        /**
         * childrenCommandStack - 子命令栈
         *
         * @type Array
         * @memberOf MacroCommand
         * */
        childrenCommandStack: [...commands],
        /**
         * execute - 执行宏命令
         *
         * @function
         * @memberOf MacroCommand
         * */
        execute: function () {
            this.childrenCommandStack.forEach(item => {
                item.execute();
            });
        },
        /**
         * add - 将命令或命令组添加至宏命令堆栈
         *
         * @function
         * @param { Command|Command[] } command - 命令
         * @memberOf MacroCommand
         * */
        add: function (command) {
            command.length !== void 0
                ? this.childrenCommandStack.push(...command)
                : this.childrenCommandStack.push(command);
        },
        /**
         * remove_single - 将命令从宏命令堆栈中移除
         *
         * @function
         * @param { Command } command - 命令
         * @return { Array } 若查询到则返回指定命令组成的数组
         * @memberOf MacroCommand
         * */
        remove_single: function (command) {
            const commandLen = this.childrenCommandStack.length;

            for (let item = 0; item < commandLen; item++) {
                if (command === this.childrenCommandStack[item]) {
                    return this.childrenCommandStack.splice(item, 1);
                }
            }

            return [];
        },
        /**
         * remove_group - 将命令组从宏命令堆栈中移除
         *
         * @function
         * @param { Command[] } commandArr - 命令组
         * @return { Array } 若查询到则返回指定命令组成的数组
         * @memberOf MacroCommand
         * */
        remove_group: function (commandArr) {
            const commandSet = new Set(commandArr);
            const commandLen = this.childrenCommandStack.length;

            const reArr = [];
            for (let item = 0; item < commandLen; item++) {
                if (commandSet.has(this.childrenCommandStack[item])) {
                    reArr.push(...this.childrenCommandStack.splice(item, 1));
                }
            }

            return reArr;
        },
        /**
         * remove - 将命令或命令组从宏命令堆栈中移除代理函数
         *
         * @function
         * @param { Command|Command[] } command - 命令或命令组
         * @return { Array } 若查询到则返回指定命令组成的数组
         * @memberOf MacroCommand
         * */
        remove: function (command) {
            let reArr;

            command.length !== void 0
                ? reArr = this.remove_group(command)
                : reArr = this.remove_single(command);

            return reArr;
        }
    }
}

export default {
    Command,
    MacroCommand
}
